package com.joe.gui.jdk6;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.Paint;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.SwingUtilities;

/**
 * 滚动字幕面板。
 * 
 * @author Chen Wei
 */
public class Canvas extends javax.swing.JPanel implements Runnable {

	/** Creates new form Canvas */
	public Canvas() {
		initComponents();
		myInit();
	}

	/**
	 * This method is called from within the constructor to initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	@SuppressWarnings("unchecked")
	// <editor-fold defaultstate="collapsed"
	// desc="Generated Code">//GEN-BEGIN:initComponents
	private void initComponents() {

		btnOK = new javax.swing.JButton();

		setBackground(new java.awt.Color(0, 0, 0));
		setForeground(new java.awt.Color(255, 255, 255));
		addMouseListener(new java.awt.event.MouseAdapter() {
			public void mousePressed(java.awt.event.MouseEvent evt) {
				formMousePressed(evt);
			}
		});
		addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
			public void mouseDragged(java.awt.event.MouseEvent evt) {
				formMouseDragged(evt);
			}
		});
		setLayout(null);

		btnOK.setText("OK");
		btnOK.setFocusPainted(false);
		btnOK.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				btnOKActionPerformed(evt);
			}
		});
		add(btnOK);
		btnOK.setBounds(400, 300, 93, 23);
	}// </editor-fold>//GEN-END:initComponents

	private void btnOKActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_btnOKActionPerformed
		stop();
		System.exit(0);
	}// GEN-LAST:event_btnOKActionPerformed

	private void formMouseDragged(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_formMouseDragged
		Point draggedPoint = evt.getLocationOnScreen();
		Point location = SwingUtilities.getRoot(this).getLocationOnScreen();
		int x = draggedPoint.x - pressedPoint.x;
		int y = draggedPoint.y - pressedPoint.y;
		SwingUtilities.getRoot(this)
				.setLocation(location.x + x, location.y + y);
		pressedPoint = draggedPoint;
	}// GEN-LAST:event_formMouseDragged

	private void formMousePressed(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_formMousePressed
		pressedPoint = evt.getLocationOnScreen();
	}// GEN-LAST:event_formMousePressed

	// Variables declaration - do not modify//GEN-BEGIN:variables
	private javax.swing.JButton btnOK;
	// End of variables declaration//GEN-END:variables

	public final int ANIMATION_WIDTH = 350;
	public final int ANIMATION_HEIGHT = 200;
	public final int SEALEVEL = 160;
	public final int OFFSET_H = 150;
	public final int OFFSET_V = 130;
	private String[] captions = new String[] { "Splash Sample - 0.1", " ",
			"Using Java 2D and Swing.", " ", "Development:", "    Chen Wei",
			" ", "Visit www.chenwei.mobi for infomation." };
	private Thread animationLoop;
	private volatile boolean noStopRequested = false;
	private int speed = 20;
	private BufferedImage bg;
	private BufferedImage animation;
	private Paint paint1;
	private Paint paint2;
	private Rectangle rect1;
	private Rectangle rect2;

	private Point pressedPoint;

	public void myInit() {
		try {
			bg = ImageIO.read(getClass().getResource(
					"/com/joe/gui/jdk6/DIVX.png"));
		} catch (IOException ex) {
		}
		this.setPreferredSize(new Dimension(bg.getWidth(), bg.getHeight()));

		animation = new BufferedImage(ANIMATION_WIDTH, ANIMATION_HEIGHT,
				BufferedImage.TYPE_INT_RGB);

		rect1 = new Rectangle(0, 0, ANIMATION_WIDTH, SEALEVEL);
		rect2 = new Rectangle(0, SEALEVEL, ANIMATION_WIDTH, ANIMATION_HEIGHT);

		Point2D start = new Point2D.Float(0, 20);
		Point2D end = new Point2D.Float(0, SEALEVEL);
		float[] dist = { 0.0f, 0.5f, 0.8f, 1.0f };
		Color[] colors = { Color.BLACK, Color.WHITE, Color.WHITE,
				new Color(0, 51, 204) };
		paint1 = new LinearGradientPaint(start, end, dist, colors);

		paint2 = new GradientPaint(0, SEALEVEL, new Color(0, 51, 204), 0,
				ANIMATION_HEIGHT, Color.BLACK);
	}

	@Override
	public void paintComponent(Graphics g) {
		super.paintComponent(g);

		if (noStopRequested == false) {
			start();
		}
		g.drawImage(bg, 0, 0, this);
	}

	@Override
	public void run() {
		Graphics2D g2d = animation.createGraphics();
		int fh = g2d.getFontMetrics().getHeight();
		int rollOffset = 0;
		while (noStopRequested) {
			try {
				Thread.sleep(speed);
			} catch (InterruptedException e) {
			}

			rollOffset = (rollOffset + 1) % (SEALEVEL + fh * captions.length);
			updateFrame(g2d, rollOffset, captions);

			repaint();
		}
		g2d.dispose();
	}

	public void updateFrame(Graphics2D g2d, int offset, String[] captions) {

		g2d.setColor(Color.BLACK);
		g2d.fillRect(0, 0, ANIMATION_WIDTH, ANIMATION_HEIGHT);

		g2d.setColor(Color.WHITE);
		int upwardsOffset = SEALEVEL;
		int adownOffset = SEALEVEL;
		int y = 0;
		int fh = g2d.getFontMetrics().getHeight();
		int ascent = g2d.getFontMetrics().getAscent();
		int descent = g2d.getFontMetrics().getDescent();
		for (String s : captions) {
			TextLayout textLayout = new TextLayout(s, getFont(), g2d
					.getFontRenderContext());

			y = upwardsOffset + ascent - offset;
			if (y < SEALEVEL + ascent) {
				g2d.setClip(rect1);
				g2d.setPaint(paint1);
				g2d.fill(textLayout.getOutline(g2d.getTransform()));
				textLayout.draw(g2d, 0, y);
				g2d.setClip(null);
				g2d.setPaint(null);
			}
			upwardsOffset += fh;

			// 绘制倒影
			y = adownOffset - descent + offset;
			if (y < ANIMATION_HEIGHT + ascent) {
				AffineTransform at = g2d.getTransform();

				g2d.setClip(rect2);
				g2d.setPaint(paint2);
				g2d.fill(textLayout.getOutline(g2d.getTransform()));
				textLayout.draw(g2d, 0, y);

				g2d.setTransform(at);
				g2d.setClip(null);
				g2d.setPaint(null);
			}
			adownOffset -= fh;
		}

		bg.createGraphics().drawImage(animation, OFFSET_H, OFFSET_V, this);
	}

	public void start() {
		noStopRequested = true;
		animationLoop = new Thread(this);
		animationLoop.setPriority(Thread.MIN_PRIORITY);
		animationLoop.start();
	}

	public void stop() {
		noStopRequested = false;
		if (animationLoop != null) {
			animationLoop.interrupt();
		}
		animationLoop = null;
	}
}